package com.icinfo.cloud.provider.punish.config.dto;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.icinfo.cloud.provider.common.constant.Constant;
import com.icinfo.cloud.provider.common.exception.BusinessException;
import com.icinfo.cloud.provider.punish.config.enums.DiscretionRuleApplyTypeEnum;
import com.icinfo.cloud.provider.punish.config.enums.DiscretionRuleConfigTypeEnum;
import com.icinfo.cloud.provider.punish.config.enums.DiscretionRuleTypeEnum;
import com.icinfo.cloud.provider.punish.config.model.ConfigOrgRegulatoryDiscretion;
import com.icinfo.cloud.provider.punish.config.model.ConfigOrgRegulatoryDiscretionRule;
import com.icinfo.framework.tools.utils.StringUtils;
import lombok.Data;
import org.hibernate.validator.constraints.Length;

import javax.validation.constraints.DecimalMin;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;

/**
 * 自由裁量规则配置对象
 *
 * @author Junfeng.Chen
 * @date 2024/1/31 8:36
 **/
@Data
public class ConfigOrgRegulatoryDiscretionRuleDto {
    /**
     * 事项违法情形 ConfigOrgRegulatoryDiscretionRule.id
     */
    private String id;

    /**
     * 违法情形（自由裁量规则）名称
     */
    @NotEmpty(message = "规则名称不能为空")
    @Length(min = 1, max = 200, message = "规则名称仅允许1-200位")
    private String ruleName;

    /**
     * 违法情形规则类型
     */
    private DiscretionRuleTypeEnum ruleType;

    /**
     * 金额下限
     */
    @DecimalMin(value = "0", message = "金额最小为0")
    private BigDecimal lowerLimitAmount;

    /**
     * 金额上限
     */
    @DecimalMin(value = "0", message = "金额最小为0")
    private BigDecimal upperLimitAmount;

    /**
     * 固定金额
     */
    @DecimalMin(value = "0", message = "金额最小为0")
    private BigDecimal fixAmount;

    /**
     * 适用简易案件 0不适用 1适用
     */
    @NotBlank(message = "请选择简易适用情况")
    private String applySimple;

    /**
     * 适用普通案件 0不适用 1适用
     */
    @NotBlank(message = "请选择普通适用情况")
    private String applyNormal;

    /**
     * 排序
     */
    private Long sort;

    /**
     * 档次等级
     */
    @NotBlank(message = "档次等级不能为空")
    @Length(min = 1, max = 8, message = "档次等级仅允许1-8位")
    private String gradeLevel;

    /**
     * 处罚种类,逗号隔开
     */
    @NotEmpty(message = "处罚种类不能为空")
    private List<String> punishKinds;



    public ConfigOrgRegulatoryDiscretionRule convertRule(ConfigOrgRegulatoryDiscretion discretion,
                                                                DiscretionRuleApplyTypeEnum applyType,
                                                         DiscretionRuleConfigTypeEnum configType) {
        ConfigOrgRegulatoryDiscretionRule entity = new ConfigOrgRegulatoryDiscretionRule();
        // 如果存在id则设置
        if (StrUtil.isNotBlank(this.getId())) {
            entity.setId(this.getId());
        }
        entity.setDiscretionId(discretion.getId());
        entity.setRuleHisId(StringUtils.uuid());
        entity.setOrgCode(discretion.getOrgCode());
        entity.setConfigType(configType.getCode());
        entity.setRegulatoryCatalogId(discretion.getRegulatoryCatalogId());
        entity.setApplyType(applyType.getCode());
        entity.setRuleName(this.getRuleName());
        entity.setRuleType(Objects.isNull(this.getRuleType()) ? null : this.getRuleType().getCode());
        entity.setLowerLimitAmount(this.getLowerLimitAmount());
        entity.setUpperLimitAmount(this.getUpperLimitAmount());
        entity.setFixAmount(this.getFixAmount());
        entity.setApplySimple(this.getApplySimple());
        entity.setApplyNormal(this.getApplyNormal());
        entity.setGradeLevel(this.getGradeLevel());
        entity.setPunishKinds(CollUtil.join(this.punishKinds, ","));
        return entity;
    }


    /**
     * 规则校验
     */
    public static void check(List<String> punishTypes, ConfigOrgRegulatoryDiscretionRuleDto ruleDto) {
        whetherApplyCheck(punishTypes, ruleDto);
        rangeCheck(ruleDto);
        fixCheck(ruleDto);
        punishTypesCheck(ruleDto);
    }

    private static void punishTypesCheck(ConfigOrgRegulatoryDiscretionRuleDto ruleDto) {
        if (ruleDto.getPunishKinds().contains("罚款") && Objects.isNull(ruleDto.getRuleType())) {
            throw new BusinessException("缺少罚款方式");
        }
        if (!ruleDto.getPunishKinds().contains("罚款") && Objects.nonNull(ruleDto.getRuleType())) {
            throw new BusinessException("无罚款处罚种类，不能选择罚款方式");
        }
    }

    private static void whetherApplyCheck(List<String> punishTypes, ConfigOrgRegulatoryDiscretionRuleDto ruleDto) {
        if (Constant.STRING_0.equals(ruleDto.getApplySimple()) && Constant.STRING_0.equals(ruleDto.getApplyNormal())) {
            throw new BusinessException("请选择适用类型！");
        }
        if (CollUtil.isEmpty(punishTypes)) {
            // 如果为空 则视为适用所有类型
            return;
        }
        if (Constant.STRING_1.equals(ruleDto.getApplyNormal()) && !punishTypes.contains(Constant.STRING_2)) {
            throw new BusinessException("该事项不适用普通案件的违法情形");
        }
        if (Constant.STRING_1.equals(ruleDto.getApplySimple()) && !punishTypes.contains(Constant.STRING_1)) {
            throw new BusinessException("该事项不适用简易案件的违法情形");
        }

    }

    /**
     * 范围金额校验
     */
    private static void rangeCheck(ConfigOrgRegulatoryDiscretionRuleDto ruleDto) {
        if (!DiscretionRuleTypeEnum.RANGE.equals(ruleDto.getRuleType())) {
            return;
        }
        if (Objects.nonNull(ruleDto.getFixAmount())) {
            throw new BusinessException(String.format("[%s]区间金额时，固定金额只能为null", ruleDto.getRuleName()));
        }
        if (ruleDto.getLowerLimitAmount().compareTo(ruleDto.getUpperLimitAmount()) > 0) {
            throw new BusinessException(String.format("[%s]下限金额不能大于上限金额", ruleDto.getRuleName()));
        }
    }

    /**
     * 固定金额校验
     */
    private static void fixCheck(ConfigOrgRegulatoryDiscretionRuleDto ruleDto) {
        if (!DiscretionRuleTypeEnum.FIX.equals(ruleDto.getRuleType())) {
            return;
        }
        if (Objects.nonNull(ruleDto.getLowerLimitAmount()) || Objects.nonNull(ruleDto.getUpperLimitAmount())) {
            throw new BusinessException(String.format("[%s]固定金额时，上限与下限金额只能为null", ruleDto.getRuleName()));
        }
    }



}
